/*
 * Copyright (C) 2009 Apple Inc. All rights reserved.
 * Copyright (C) 2014 Sony Computer Entertainment Inc.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 * THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "config.h"

#if ENABLE(GEOLOCATION)
#include "GeolocationClientManx.h"

#include "Document.h"
#include "Frame.h"
#include "GeolocationController.h"
#include "GeolocationPosition.h"
#include "SecurityOrigin.h"
#include "WebViewPrivate.h"
#include <wtf/MainThread.h>

namespace WebCore {

static String getOrigin(Frame* frame) 
{
    String origin; 
    SecurityOrigin* securityOrigin = frame->document()->securityOrigin();

    // Special case for file.
    if (securityOrigin->protocol() == "file")
        origin = "null";
    else
        origin = securityOrigin->toString();

    return origin;
}

GeolocationClientManx::GeolocationClientManx(WebKit::WebViewPrivate* webView)
    : m_webView(webView)
    , m_controller(0)
    , m_pendingPermissionRequestListener(0)
{
}

GeolocationClientManx::~GeolocationClientManx()
{
}

void GeolocationClientManx::geolocationDestroyed()
{
    m_webView->client().stopGeolocationUpdating();
    m_lastPosition.clear();
    m_pendingPermissionRequestListener = 0;
    m_controller = 0;
}

void GeolocationClientManx::startUpdating()
{
    m_webView->client().startGeolocationUpdating();
}

void GeolocationClientManx::stopUpdating()
{
    m_webView->client().stopGeolocationUpdating();
}

void GeolocationClientManx::setEnableHighAccuracy(bool)
{
}

GeolocationPosition* GeolocationClientManx::lastPosition()
{
    return m_lastPosition.get();
}

void GeolocationClientManx::requestPermission(Geolocation* location)
{
    // Forget previous permission request.
    m_pendingPermissionRequestListener = 0;

    Frame* frame = location->frame();
    if (!frame)
        return;

    const String origin = getOrigin(frame);
    // Special case for documents with the isUnique flag on. (ie. sandboxed iframes)
    if (origin == "null") {
        location->setIsAllowed(false);
        return;
    }

    m_pendingPermissionRequestListener = location;
    m_webView->client().requestGeolocationPermission(origin);
}

void GeolocationClientManx::cancelPermissionRequest(Geolocation* location)
{
    ASSERT(!m_pendingPermissionRequestListener || m_pendingPermissionRequestListener == location);
    Frame* frame = location->frame();
    if (!frame)
        return;

    const String origin = getOrigin(frame);
    // Special case for documents with the isUnique flag on. (ie. sandboxed iframes)
    if (origin == "null")
        return;

    m_webView->client().cancelGeolocationPermissionRequest(origin);
    m_pendingPermissionRequestListener = 0;
}

void GeolocationClientManx::setController(GeolocationController* controller)
{
    m_controller = controller;
}

void GeolocationClientManx::setGeolocationPermission(const char* origin, bool isAllowed)
{
    ASSERT(isMainThread());
    if (m_pendingPermissionRequestListener)
        m_pendingPermissionRequestListener->setIsAllowed(isAllowed);

    m_pendingPermissionRequestListener = 0;
}

void GeolocationClientManx::updateGeolocationPosition(const WebKit::WebViewGeolocationPosition* position)
{
    ASSERT(isMainThread());
    ASSERT(position);
    if (!m_controller)
        return;

    if (position->m_canProvideLatitude && position->m_canProvideLongitude && position->m_canProvideAccuracy)
        m_lastPosition = WebCore::GeolocationPosition::create(
            position->m_timestamp,
            position->m_latitude,
            position->m_longitude,
            position->m_accuracy,
            position->m_canProvideAltitude,
            position->m_altitude,
            position->m_canProvideAltitudeAccuracy,
            position->m_altitudeAccuracy,
            position->m_canProvideHeading,
            position->m_heading,
            position->m_canProvideSpeed,
            position->m_speed
            );
    else
        m_lastPosition.clear();

    if (m_lastPosition)
        m_controller->positionChanged(m_lastPosition.get());
}

void GeolocationClientManxNullified::requestPermission(Geolocation* location)
{
    location->setIsAllowed(false);
}

} // namespace WebCore

#endif // ENABLE(GEOLOCATION)
